/* Blink Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_event.h"


#include "mymqtt.h"
#include "mywifi.h"
#include "cleaner.h"
#include "cJSON.h"
#include "myuart.h"
#include "myble.h"

//全局变量区
cleaner* CleanerCar = NULL;

QueueHandle_t xQueueMqtt2Uart;
QueueHandle_t xQueueUart2Mqtt;

static const char *TAG = "EXAMPLE";


static void uart_send_task(void *arg);

static void uart_receive_task(void *arg);

//BLE WIFI TASK
static void blefi_task(void *arg);

void app_main(void)
{
    //Initialize NVS
    esp_err_t ret = nvs_flash_init();
    ESP_ERROR_CHECK(ret);
    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
    
    // //创建消息队列  
    xQueueMqtt2Uart = xQueueCreate(1, sizeof(uint8_t)*3);
    xQueueUart2Mqtt = xQueueCreate(1, sizeof(uint8_t)*3);
    uart_init();
    xTaskCreate(uart_send_task, "uart_send_task", 4096, NULL, 10, NULL);
    xTaskCreate(uart_receive_task, "uart_receive_task", 4096, NULL, 12, NULL);


    //得到小车默认配置
    CleanerCar = get_cleaner();
    //从flash里获得小车之前的配置，如果是第一次上电，就没有
    ret = get_cleanerConfig_from_nvs(CleanerCar);
    if (ret != ESP_OK)
    {
        //如果是第一次上电，把默认的配置储存到nvs中
        store_cleanerConfig_to_nvs(CleanerCar);
    }
    
    //串口连接小车，获取小车状态,按照配置设定小车工作时间
    uart_config_car();
    printf("finish config car \n");
    
    //首先尝试连接wifi
    uint8_t wifi_sta = CONN_FAIL;
    set_wifi_config_from_nvs();
    wifi_init();   
    wifi_sta = app_wifi_wait_connected();  
    //阻塞，等待WiFi连接结果
    if (wifi_sta == CONN_OK)
    {
         //wifi连接成功，开启mqtt，连接物联网平台 
        printf("mqtt_start \n");  
        mqtt_start();
    }
    else
    {
        xTaskCreate(blefi_task, "blefi_task", 4096, NULL, 10, NULL);
    }


    while(1) {
        
        wifi_sta = get_wifi_status();
        if (wifi_sta == CONN_OK)
        {
          
        }
        else
        {
            xTaskCreate(blefi_task, "blefi_task", 4096, NULL, 10, NULL);
            wifi_sta = app_wifi_wait_connected();  
            //阻塞，等待WiFi连接结果
            if (wifi_sta == CONN_OK)
            {
                printf("mqtt_reconnect \n");  
                mqtt_reconnect();
            }
        }
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        //printf("\ndelay 2s \n");
    }
}






static void blefi_task(void *arg)
{
    static const char *BLEFI_TAG = "BLEFI";
    // Configure a temporary buffer for the incoming data
    //uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
    uint8_t wifi_sta;
    //清除wifi的groupbit 断开wifi连接
    reset_wifi();

    ble_start();
    vTaskDelay(5000 / portTICK_PERIOD_MS);
    do
    {
        wifi_sta = app_wifi_wait_connected();
        if(wifi_sta == CONN_FAIL){
            ESP_LOGI(BLEFI_TAG, "\n connect failed \n");  
        }
        else if(wifi_sta == CONN_OK){
            ESP_LOGI(BLEFI_TAG, "\n connected \n");  
            set_wifi_status(wifi_sta);
            //store_wificonfig_to_nvs();
            printf("\n set wifi status \n");    
        }
        else
        {
            ESP_LOGI(BLEFI_TAG, "unexcept wifi\n"); 
        }
        
        /* code */
    } while (wifi_sta != CONN_OK);
    bt_close();
    //wifi connected
    
    vTaskDelete(NULL);

}



static void uart_send_task(void *arg)
{
    // Configure a temporary buffer for the incoming data
    uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
    static uint8_t receivebuffer[3] = {0};
    while (1) {
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        
        xQueueReceive(  xQueueMqtt2Uart, /* 消息队列句柄 */
                        receivebuffer, /* 接收消息队列数据的缓冲地址 */
                        portMAX_DELAY /* 等待消息队列有数据的最大等待时间 */
                        );
        printf("get data from mqtt \n");

        //封包处理
        set_uart_pack(receivebuffer, 3, data);

        uart_write_bytes(UART_PORT, (const char *) data, 5);
    
    }
}

//warn 有可能轮询读了小车发了两次数据
static void uart_receive_task(void *arg)
{
    uint8_t sendbuffer[3] = {0};
    int len = 0;
    // Configure a temporary buffer for the incoming data
    uint8_t *data = (uint8_t *) malloc(BUF_SIZE);  
    while (1) {
        // Read data from the UART
        //printf("wait data in uart_receive_task\n");
        len = uart_read_bytes(UART_PORT, data, BUF_SIZE, 20 / portTICK_RATE_MS);
        //uart_flush(UART_PORT);
        
        if (len != 0)
        {
            printf(" \ndata in uart_receive_task len is %d\n",len);
            // 
            if( len == 3){
                ESP_LOGI(TAG, "uart data  0 is %x ",data[0]);
                ESP_LOGI(TAG, "uart data  1 is %x ",data[1]);
                ESP_LOGI(TAG, "uart data  2 is %x ",data[2]);
                strncpy((char* )sendbuffer, (const char*)data, 3);
                xQueueSend( xQueueUart2Mqtt, /* 消息队列句柄 */
                            (const void*)sendbuffer, /* 要传递数据地址 */
                            portMAX_DELAY /* 等待消息队列有空间的最大等待时间 */
                            );
            }else{
                printf(" receive more than one command, number is %d\n",len/3);
                sendbuffer[0] = UART_ERROR;
                sendbuffer[1] = 0;
                sendbuffer[2] = 0;
                xQueueSend( xQueueUart2Mqtt, /* 消息队列句柄 */
                            (const void*)sendbuffer, /* 要传递数据地址 */
                            portMAX_DELAY /* 等待消息队列有空间的最大等待时间 */
                            );
            }
            
        }
        //优先级低  
        vTaskDelay(100 / portTICK_PERIOD_MS);

    }
}


